package com.stars.easyms.rest.lock;

import com.stars.easyms.redis.exception.DistributedLockTimeoutException;
import com.stars.easyms.redis.lock.DistributedLock;
import com.stars.easyms.rest.bean.RestLockInfo;
import com.stars.easyms.rest.constant.RestConstants;
import com.stars.easyms.rest.exception.RestRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>className: EasyMsRestLock</p>
 * <p>description: EasyMs的rest加锁类</p>
 *
 * @author guoguifang
 * @version 1.2.2
 * @date 2019-07-12 13:36
 */
public final class EasyMsRestLock {

    private static final Logger log = LoggerFactory.getLogger(EasyMsRestLock.class);

    private static final ThreadLocal<RestLockInfo> CURRENT_THREAD_REST_LOCK_INFO = new ThreadLocal<>();

    /**
     * 获取锁
     */
    public static void tryRestLock(RestLockInfo restLockInfo) {
        String restLockName;
        if (restLockInfo != null && StringUtils.isNotBlank(restLockName = restLockInfo.getLockName())) {
            long timeout = restLockInfo.getTimeout();
            boolean lockFlag = false;
            if (timeout > 0) {
                try {
                    DistributedLock.tryBlockLock(RestConstants.REST_LOCK, restLockName, restLockInfo.getExpireSecond(), restLockInfo.getTimeout(), restLockInfo.getRetryInterval());
                    lockFlag = true;
                } catch (DistributedLockTimeoutException e) {
                    // 正常流程，无需使用error级别
                    log.info(e.getMessage());
                }
            } else {
                lockFlag = DistributedLock.tryLock(RestConstants.REST_LOCK, restLockName, restLockInfo.getExpireSecond());
            }
            if (!lockFlag) {
                String lockFailMsg;
                if (StringUtils.isBlank(lockFailMsg = restLockInfo.getLockFailMsg())) {
                    lockFailMsg = "";
                }
                throw new RestRuntimeException(lockFailMsg);
            }
            CURRENT_THREAD_REST_LOCK_INFO.set(restLockInfo);
        }
    }

    /**
     * 释放锁
     */
    public static void releaseRestLock() {
        RestLockInfo restLockInfo = CURRENT_THREAD_REST_LOCK_INFO.get();
        if (restLockInfo != null) {
            DistributedLock.unlock(RestConstants.REST_LOCK, restLockInfo.getLockName());
            CURRENT_THREAD_REST_LOCK_INFO.remove();
        }
    }

    private EasyMsRestLock() {}
}